package controller

import (
	"context"
	"encoding/json"
	"net/url"
	"sale-admin/config/mysql"
	"sale-admin/internal/app/web/service/common"
	"sale-admin/internal/app/web/service/express"
	"sale-admin/internal/dao"
	"sale-admin/internal/define"
	"sale-admin/internal/models"
	"strconv"

	"192.168.1.75/go-pkg/logx"
	"192.168.1.75/go-pkg/response"
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
)

type ExpressFeeSetting struct{}

func (ExpressFeeSetting) Create(c *gin.Context) {
	var params struct {
		Name                 string               `json:"name"`
		ShippingFromProvince string               `json:"shipping_from_province"`
		ShippingFromCity     string               `json:"shipping_from_city"`
		PricingType          int                  `json:"pricing_type"`
		FreeShippingProvince string               `json:"free_shipping_province"`
		PricingConfig        []dao.PricingConfigT `json:"pricing_config"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	pricingConfigJs, _ := json.Marshal(params.PricingConfig)
	id, err := express.ExpressFeeSetting{}.Create(
		c.Request.Context(),
		params.Name,
		params.ShippingFromProvince,
		params.ShippingFromCity,
		params.PricingType,
		params.FreeShippingProvince,
		string(pricingConfigJs),
	)
	response.JSON(c, gin.H{
		"id": id,
	}, err)
}
func (ExpressFeeSetting) Update(c *gin.Context) {
	var params struct {
		ID                   string               `json:"id"`
		Name                 string               `json:"name"`
		ShippingFromProvince string               `json:"shipping_from_province"`
		ShippingFromCity     string               `json:"shipping_from_city"`
		PricingType          int                  `json:"pricing_type"`
		FreeShippingProvince string               `json:"free_shipping_province"`
		PricingConfig        []dao.PricingConfigT `json:"pricing_config"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	pricingConfigJs, _ := json.Marshal(params.PricingConfig)
	err := express.ExpressFeeSetting{}.Update(
		c.Request.Context(),
		params.ID,
		params.Name,
		params.ShippingFromProvince,
		params.ShippingFromCity,
		params.PricingType,
		params.FreeShippingProvince,
		string(pricingConfigJs),
	)
	response.JSON(c, nil, err)
}
func (ExpressFeeSetting) Delete(c *gin.Context) {
	var params struct {
		ID string `json:"id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := express.ExpressFeeSetting{}.Delete(c.Request.Context(), params.ID)
	response.JSON(c, nil, err)
}
func (ExpressFeeSetting) List(c *gin.Context) {
	name := c.Query("name")
	pricingType, _ := strconv.Atoi(c.Query("pricing_type"))
	page, _ := strconv.Atoi(c.Query("page"))
	limit, _ := strconv.Atoi(c.Query("limit"))
	list, total := express.ExpressFeeSetting{}.List(c.Request.Context(), name, pricingType, page, limit)
	response.JSON(c, gin.H{
		"list":  list,
		"total": total,
	}, nil)
}
func (ExpressFeeSetting) Detail(c *gin.Context) {
	id := c.Query("id")
	detail, err := express.ExpressFeeSetting{}.Detail(c.Request.Context(), id)
	response.JSON(c, detail, err)
}

type Express struct{}

// CompanyList 快读公司列表
func (Express) CompanyList(c *gin.Context) {
	list := express.Express{}.Company(c.Request.Context(), c.Query("company"))
	response.JSON(c, list, nil)
}

// SetShippingInfo 设置物流信息
func (Express) SetShippingInfo(c *gin.Context) {
	var params struct {
		OutTradeNO string `json:"out_trade_no"`
		ExpressCom string `json:"express_com"`
		ExpressNum string `json:"express_num"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	// 保存物流信息
	err := express.Express{}.SetShipmentInfo(
		c.Request.Context(),
		params.OutTradeNO,
		params.ExpressCom,
		params.ExpressNum,
	)
	if err == nil {
		// 修改订单状态为已发货
		mysql.NewDB().Model(&models.MaOrder{}).
			Where("out_trade_no = ?", params.OutTradeNO).
			Updates(map[string]interface{}{
				"order_status": define.OrderStatus_Shipped, // 已发货
			})
		common.Order{}.OrderStatusNotify(c.Request.Context(), params.OutTradeNO, 4)
	}
	response.JSON(c, nil, err)
}

type KD100PushParam struct {
	Status     string `json:"status"`
	Billstatus string `json:"billstatus"`
	Message    string `json:"message"`
	LastResult struct {
		Message string `json:"message"`
		NU      string `json:"nu"`
		Ischeck string `json:"ischeck"`
		Com     string `json:"com"`
		State   string `json:"state"`
		Data    []struct {
			Time       string `json:"time"`
			Context    string `json:"context"`
			Ftime      string `json:"ftime"`
			AreaCode   string `json:"areaCode"`
			AreaName   string `json:"areaName"`
			Status     string `json:"status"`
			Location   string `json:"location"`
			AreaCenter string `json:"areaCenter"`
			AreaPinYin string `json:"areaPinYin"`
			StatusCode string `json:"statusCode"`
		} `json:"data"`
	} `json:"lastResult"`
}
type KD100PushBody struct {
	Sign  string `json:"sign" form:"sign"`
	Param string `json:"param" form:"param"`
}

// ShippingTrack 物流跟踪
func (Express) ShippingTracking(c *gin.Context) {
	var body KD100PushBody
	c.ShouldBind(&body)
	logx.Info(context.Background(), "kuaidi100 param", logx.Any("param", body))
	var param KD100PushParam
	decodedParam, err := url.QueryUnescape(body.Param)
	if err != nil {
		response.JSON(c, gin.H{
			"result":     false,
			"returnCode": "500",
			"message":    "失败",
		}, nil)
		return
	}
	json.Unmarshal([]byte(decodedParam), &param)
	detail := dao.OrderShipmentInfo{}.Detail(
		c.Request.Context(),
		mysql.NewDB(),
		"",
		param.LastResult.Com,
		param.LastResult.NU,
	)
	if detail == nil {
		logx.Error(context.Background(), "invalid OrderShipmentInfo", logx.Any("param", param))
		c.JSON(200, gin.H{
			"result":     false,
			"returnCode": "500",
			"message":    "失败",
		})
		return
	}
	if len(param.LastResult.Data) > 0 {
		dataJson, _ := json.Marshal(param.LastResult.Data)
		// 创建或更新轨迹信息
		dao.OrderShippingTracking{}.Create(
			c.Request.Context(),
			mysql.NewDB(),
			models.OrderShippingTracking{
				OutTradeNo: detail.OutTradeNo,
				ExpressCom: param.LastResult.Com,
				ExpressNum: param.LastResult.NU,
				Data:       string(dataJson),
			},
		)
	}
	// 已签收，更新订单状态为已完成
	if param.LastResult.State == "3" {
		mysql.NewDB().Model(&models.MaOrder{}).
			Where("out_trade_no = ?", detail.OutTradeNo).
			Updates(map[string]interface{}{
				"order_status": define.OrderStatus_Completed, // 更新订单状态为已完成
			})
		err := common.Order{}.OrderStatusNotify(c.Request.Context(), detail.OutTradeNo, 5)
		if err != nil {
			c.JSON(200, gin.H{
				"result":     false,
				"returnCode": "500",
				"message":    "失败",
			})
			return
		}
	}
	// 返回接收结果
	c.JSON(200, gin.H{
		"result":     true,
		"returnCode": "200",
		"message":    "成功",
	})
}
